package main

import (
	"fmt"
	"reflect"
	"time"
)

type T struct {
	name string
}

func (t T) Get() string {
	return t.name
}

func (t *T) Set(name string) {
	t.name = name
}

func (t T) Print() {
	fmt.Printf("t.name=%s\n", t.name)
}
func (t *T) Pprint() {
	fmt.Printf("*t.name=%s\n", t.name)
}

func main() {

	// TestMethodEquallyCall()
	TestMethodSet()
}

func TestMethodEquallyCall() {

	t := T{}
	t.Set("Gopher")
	fmt.Printf("get t.name: %s\n", t.Get())

	(*T).Set(&t, "NewGopher")
	fmt.Printf("get new t.name: %s\n", T.Get(t))

	arr := []T{{"one"}, {"two"}, {"three"}}
	for _, v := range arr {
		go v.Print() // 等价于 go T.Print(v)
	}
	for _, v := range arr {
		go v.Pprint() // 等价于 go (*T).Print(&v)
	}

	time.Sleep(time.Second * 1)
}

func dumpMethodSet(i interface{}, name string) {

	fmt.Printf("dump method set of %s...\n", name)
	dynType := reflect.TypeOf(i)

	if dynType == nil {
		fmt.Printf("no dynamic type!\n")
	}
	n := dynType.NumMethod()
	if n <= 0 {
		fmt.Printf("no method!\n")
	}

	for i := 0; i < n; i++ {
		fmt.Printf("  - %s\n", dynType.Method(i).Name)
	}
}

func TestMethodSet() {

	t1 := T{}
	t2 := &T{}
	dumpMethodSet(t1, "T")
	dumpMethodSet(t2, "*T")

	type AT T
	at1 := AT{}
	at2 := &AT{}
	dumpMethodSet(at1, "AT")
	dumpMethodSet(at2, "*AT")

	type I interface {
		DoNothing()
	}

	type ST struct {
		T
		I
	}
	st1 := ST{}
	st2 := &ST{}
	dumpMethodSet(st1, "ST")
	dumpMethodSet(st2, "*ST")
}
